package com.lezheba.db;

import org.apache.log4j.Logger;
import org.hibernate.HibernateException;
import org.hibernate.Interceptor;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {
	static Logger logger = Logger.getLogger(HibernateUtil.class.getName());
    private static SessionFactory sessionFactory;  

	private static final ThreadLocal<Session> threadSession = new ThreadLocal<Session>();  
    private static final ThreadLocal<Transaction> threadTransaction = new ThreadLocal<Transaction>();  
    private static final ThreadLocal<Interceptor> threadInterceptor = new ThreadLocal<Interceptor>();  
  
    // Create the initial SessionFactory from the default configuration files  
    static {  
        try {  
            sessionFactory = new Configuration().configure().buildSessionFactory();  
        } catch (Throwable ex) {  
        	logger.error("Building SessionFactory failed.", ex);  
            throw new ExceptionInInitializerError(ex);  
        }  
    }  
 
    public static SessionFactory getSessionFactory() {  
        return sessionFactory;  
    }  
  
 
     public static void rebuildSessionFactory(){
        synchronized(sessionFactory) {  
            try {  
                sessionFactory = new Configuration().buildSessionFactory();  
            } catch (Exception ex) {  

            }  
        }  
     }  
  
 
     public static void rebuildSessionFactory(Configuration cfg)   {  
        synchronized(sessionFactory) {  
            try {  
                sessionFactory = cfg.buildSessionFactory();  
            } catch (Exception ex) {  

            }  
        }  
     }  
  

	public static Session getSession() {  
        Session s = threadSession.get();  
        try {  
            if (s == null) {  
            	logger.debug("Opening new Session for this thread.");  
                if (getInterceptor() != null) {  
                	logger.debug("Using interceptor: " + getInterceptor().getClass());  
                    s = getSessionFactory().openSession(getInterceptor());  
                } else {  
                    s = getSessionFactory().openSession();  
                }  
                threadSession.set(s);  
            }  
        } catch (HibernateException ex) {  
 
        }  
        return s;  
    }  
  
    public static void closeSession()  {  
        try {  
            Session s = threadSession.get();  
            threadSession.set(null);  
            if (s != null && s.isOpen()) {  
            	logger.debug("Closing Session of this thread.");  
                s.close();  
            }  
        } catch (HibernateException ex) {  
 
        }  
    }  
  

    public static void beginTransaction()   {  
        Transaction tx = threadTransaction.get();  
        try {  
            if (tx == null) {  
            	logger.debug("Starting new database transaction in this thread.");  
                tx = getSession().beginTransaction();  
                threadTransaction.set(tx);  
            }  
        } catch (HibernateException ex) {  

        }  
    }  
  
 
    public static void commitTransaction()   {  
        Transaction tx = threadTransaction.get();  
        try {  
            if ( tx != null && !tx.wasCommitted()  
                            && !tx.wasRolledBack() ) {  
            	logger.debug("Committing database transaction of this thread.");  
                tx.commit();  
            }  
            threadTransaction.set(null);  
        } catch (HibernateException ex) {  
            rollbackTransaction();  
        }  
    }  
  
    /** 
     * Commit the database transaction. 
     */  
    public static void rollbackTransaction()   {  
        Transaction tx = threadTransaction.get();  
        try {  
            threadTransaction.set(null);  
            if ( tx != null && !tx.wasCommitted() && !tx.wasRolledBack() ) {  
            	logger.debug("Tyring to rollback database transaction of this thread.");  
                tx.rollback();  
            }  
        } catch (HibernateException ex) {  
        } finally {  
            closeSession();  
        }  
    }  
  
 
    public static void registerInterceptor(Interceptor interceptor) {  
        threadInterceptor.set(interceptor);  
    }  
  
    private static Interceptor getInterceptor() {  
        Interceptor interceptor =  
            threadInterceptor.get();  
        return interceptor;  
    }  

}
